using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 登录历史应用服务实现
    /// </summary>
    public class LoginHistoryAppService : ILoginHistoryAppService
    {
        private readonly ILoginHistoryRepository _loginHistoryRepository;
        private readonly ILogger<LoginHistoryAppService> _logger;

        public LoginHistoryAppService(
            ILoginHistoryRepository loginHistoryRepository,
            ILogger<LoginHistoryAppService> logger)
        {
            _loginHistoryRepository = loginHistoryRepository;
            _logger = logger;
        }

        public async Task<IEnumerable<LoginHistoryDto>> GetAllAsync()
        {
            try
            {
                var entities = await _loginHistoryRepository.GetAllAsync();
                return entities.OrderByDescending(x => x.CreatedAt).Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all login history records");
                throw;
            }
        }

        public async Task<LoginHistoryDto?> GetByIdAsync(long id)
        {
            try
            {
                var entity = await _loginHistoryRepository.GetByIdAsync(id);
                return entity == null ? null : MapToDto(entity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting login history by id {Id}", id);
                throw;
            }
        }

        public async Task AddAsync(LoginHistoryDto dto)
        {
            try
            {
                var entity = new LoginHistory
                {
                    UserId = dto.UserId,
                    IpAddress = dto.IpAddress,
                    Location = dto.Location,
                    DeviceInfo = dto.DeviceId, // 映射到DeviceInfo字段
                    SessionId = Guid.NewGuid().ToString(),
                    CreatedAt = DateTime.UtcNow
                };

                await _loginHistoryRepository.AddAsync(entity);
                _logger.LogInformation("Login history record added successfully: {Id}", entity.Id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error adding login history record");
                throw;
            }
        }

        public async Task<LoginHistoryDto> CreateAsync(LoginHistoryDto dto)
        {
            try
            {
                var entity = new LoginHistory
                {
                    UserId = dto.UserId,
                    IpAddress = dto.IpAddress,
                    Location = dto.Location,
                    DeviceInfo = dto.DeviceId, // 映射到DeviceInfo字段
                    SessionId = Guid.NewGuid().ToString(),
                    CreatedAt = DateTime.UtcNow
                };

                await _loginHistoryRepository.AddAsync(entity);
                _logger.LogInformation("Login history record created successfully: {Id}", entity.Id);
                
                return MapToDto(entity);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating login history record");
                throw;
            }
        }

        public async Task UpdateAsync(long id, LoginHistoryDto dto)
        {
            try
            {
                var entity = await _loginHistoryRepository.GetByIdAsync(id);
                if (entity == null)
                    throw new ArgumentException($"Login history record with id {id} not found");

                entity.IpAddress = dto.IpAddress;
                entity.Location = dto.Location;
                entity.DeviceInfo = dto.DeviceId;

                await _loginHistoryRepository.UpdateAsync(id, entity);
                _logger.LogInformation("Login history record updated successfully: {Id}", id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating login history record {Id}", id);
                throw;
            }
        }

        public async Task DeleteAsync(long id)
        {
            try
            {
                var entity = await _loginHistoryRepository.GetByIdAsync(id);
                if (entity == null)
                {
                    _logger.LogWarning("Login history record not found for deletion: {Id}", id);
                    return;
                }

                await _loginHistoryRepository.DeleteAsync(id);
                _logger.LogInformation("Login history record deleted successfully: {Id}", id);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting login history record {Id}", id);
                throw;
            }
        }

    public Task<PagedResultDto<LoginHistoryDto>> GetPagedListAsync(PagedQueryDto query)
        {
            try
            {
                // 临时简单实现，避免当前项目编译问题
                var emptyResult = new List<LoginHistoryDto>();
        return Task.FromResult(new PagedResultDto<LoginHistoryDto>(emptyResult, 0, query.PageIndex, query.PageSize));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting paged login history records");
                throw;
            }
        }

        public async Task<IEnumerable<LoginHistoryDto>> GetByUserIdAsync(long userId)
        {
            try
            {
                var allItems = await GetAllAsync();
                return allItems.Where(x => x.UserId == userId).OrderByDescending(x => x.LoginTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting login history by user id {UserId}", userId);
                throw;
            }
        }

        public async Task<IEnumerable<LoginHistoryDto>> GetByDateRangeAsync(DateTime startDate, DateTime endDate)
        {
            try
            {
                var allItems = await GetAllAsync();
                return allItems.Where(x => x.LoginTime >= startDate && x.LoginTime <= endDate)
                              .OrderByDescending(x => x.LoginTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting login history by date range");
                throw;
            }
        }

        public async Task<IEnumerable<LoginHistoryDto>> GetRecentLoginsAsync(int count = 10)
        {
            try
            {
                var allItems = await GetAllAsync();
                return allItems.OrderByDescending(x => x.LoginTime).Take(count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting recent login history");
                throw;
            }
        }

        public async Task<Dictionary<string, int>> GetLoginStatisticsAsync(DateTime? startDate = null, DateTime? endDate = null)
        {
            try
            {
                var items = await GetAllAsync();
                var query = items.AsQueryable();

                if (startDate.HasValue)
                    query = query.Where(x => x.LoginTime >= startDate.Value);

                if (endDate.HasValue)
                    query = query.Where(x => x.LoginTime <= endDate.Value);

                var statistics = new Dictionary<string, int>
                {
                    { "TotalLogins", query.Count() },
                    { "UniqueUsers", query.Select(x => x.UserId).Distinct().Count() },
                    { "UniqueIPs", query.Select(x => x.IpAddress).Distinct().Count() },
                    { "TodayLogins", query.Count(x => x.LoginTime.Date == DateTime.Today) }
                };

                return statistics;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting login statistics");
                throw;
            }
        }

        private static LoginHistoryDto MapToDto(LoginHistory entity)
        {
            return new LoginHistoryDto
            {
                Id = entity.Id,
                UserId = entity.UserId,
                LoginTime = entity.CreatedAt,
                IpAddress = entity.IpAddress,
                Location = entity.Location ?? string.Empty,
                DeviceId = entity.DeviceInfo ?? entity.SessionId ?? string.Empty
            };
        }
    }
}
